package ez

import (
	"fmt"
	"sort"
)

type EzAction func(session *Session)

type EzHandler struct {
	Matcher    string
	Router     *Router
	Action     *EzAction
	ActionSort []int
	StatusCode int //允许中断
	Actions    map[int]map[string]*EzAction
	CurAction  *EzAction
	IsStop     bool
}

func NewEzHandler(router *Router, action *EzAction) *EzHandler {
	url := ConfigService.RouterPrefix + router.Group + router.Prefix + router.Url + router.Suffix
	hd := &EzHandler{
		Matcher:    url,
		Router:     router,
		Action:     action,
		ActionSort: make([]int, 0),
		CurAction:  nil,
		StatusCode: 0,
		Actions:    make(map[int]map[string]*EzAction),
		IsStop:     false,
	}
	hd.Add(50, "main", *action)
	return hd
}

func (this *EzHandler) Add(weight int, name string, action EzAction) *EzHandler {
	if weight < 10 {
		weight = 10
	}
	if weight > 100 {
		weight = 99
	}
	return this.SAdd(weight, name, action)
}

// 仅供框架使用，用于一些weight小于10或者大于99的方法的创建
func (this *EzHandler) SAdd(weight int, name string, action EzAction) *EzHandler {
	_, ok := this.Actions[weight]
	if !ok {
		this.Actions[weight] = map[string]*EzAction{name: &action}
	} else {
		this.Actions[weight][name] = &action
	}
	//重新梳理排序字段
	tmp := make([]int, 0)
	for key, _ := range this.Actions {
		tmp = append(tmp, key)
	}
	sort.Ints(tmp)
	this.ActionSort = tmp
	return this
}

func (this *EzHandler) Run(session *Session) {
	session.Handler = this
	for _, key := range this.ActionSort {
		actions, ok := this.Actions[key]
		if ok {
			groupHandlerTimer := session.Timer.Add(fmt.Sprintf("EzHandler_Weight_%d", key))
			for name, action := range actions {
				if this.IsStop {
					return
				}
				groupSonHandlerTimer := session.Timer.Add(fmt.Sprintf("EzHandler_Weight_%d_%s", key, name))
				(*action)(session)
				groupSonHandlerTimer.Done()
				//todo 这里使用协程似乎是有问题的，后面查查解决一下
			}
			groupHandlerTimer.Done()
		}
	}
}

func (this *EzHandler) AddAccessRole(role ...string) *EzHandler {
	if len(role) == 0 {
		role = []string{Role_User} //添加访问控制，默认添加一个Role_User规则
	}
	AC.Add(this.Matcher, role...)
	return this
}

func (this *EzHandler) AddAccessControl(action EzAction, role ...string) *EzHandler {
	if len(role) > 0 {
		AC.Add(this.Matcher, role...)
	}
	this.SAdd(0, "AccessControl", action)
	return this
}

func (this *EzHandler) SetRouterName(name string) *EzHandler {
	this.Router.Name = name
	return this
}
